package com.chapter.sample.controller;

import com.chapter.sample.entity.People;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.management.ClassLoadingMXBean;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;

@RestController
public class MemoryTestController {


    /**
     * 案例1:模拟线上环境OOM
     * -XX:+PrintGCDetails -XX:MetaspaceSize=64
     * -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap/heapdump.hprof
     * -XX:+PrintGCDateStamps -Xms200m -Xmx200m -Xloggc:log/gc-oomHeap.log
     * <p>
     * -XX:+PrintGCDetails -XX:MetaspaceSize=64 -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -Xms200m -Xmx200m
     *
     * jdk/17
     * -Xlog:gc* -XX:MetaspaceSize=64 -XX:+HeapDumpOnOutOfMemoryError
     * -XX:HeapDumpPath=/Library/dev/sample/chapter-common-platform/chapter-common-sample/heap/heapdump.hprof
     * -XX:+PrintGCDateStamps -Xms200m -Xmx200m -Xloggc:/Library/dev/sample/chapter-common-platform/chapter-common-sample/log/gc.log
     * -XX:+UseParallelGC
     */
    @RequestMapping("/add")
    public void addObject() {
        List<People> list = new ArrayList<>();
        while (true) {
            People people = new People();
            list.add(people);
        }
    }

    /**
     * 案例2:模拟元空间OOM溢出
     * -Xlog:gc* -XX:MetaspaceSize=60m -XX:MaxMetaspaceSize=60m -Xss512k -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Library/dev/sample/chapter-common-platform/chapter-common-sample/heap/heapdump.hprof -XX:SurvivorRatio=8 -XX:+TraceClassLoading -XX:+TraceClassUnloading -XX:PrintGCDateStamps -Xms60m -Xmx60m -Xloggc:/Library/dev/sample/chapter-common-platform/chapter-common-sample/log/gc.log -XX:+UseParallelGC
     */


    @RequestMapping("/metaSpaceOom")
    public void metaSpaceOom() {
        ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(People.class);
            //enhancer.setUseCache(false);
            enhancer.setUseCache(true);
            enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
                System.out.println("我是加强类，输出print之前的加强方法");
                return methodProxy.invokeSuper(o, objects);
            });
            People people = (People) enhancer.create();
            people.print();
            System.out.println(people.getClass());
            System.out.println("totalClass："+classLoadingMXBean.getTotalLoadedClassCount());
            System.out.println("activeClass："+classLoadingMXBean.getLoadedClassCount());
            System.out.println("unloadedClass："+classLoadingMXBean.getUnloadedClassCount());
        }
    }
}
